package com.rmfyzxfw.caseprocess.boot.handler;

import com.rmfyzxfw.caseprocess.boot.exception.AppRuntimeException;
import com.rmfyzxfw.caseprocess.boot.result.ApiResult;
import com.rmfyzxfw.caseprocess.boot.result.CommonStatusCode;
import com.rmfyzxfw.caseprocess.boot.result.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import java.sql.SQLException;
import java.util.List;

/**
 * @author lixiaoxiang
 * @Description
 * @createTime 2021年12月24日 17:24:00
 */
@Slf4j
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {


    /**
     * 运行时异常
     * @param e
     * @return
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ApiResult errorHandle(RuntimeException e){
        log.error("异常信息：{}", e.getMessage(), e);
        return R.fail(CommonStatusCode._1003, e.getMessage());
    }


    /**
     * 编译期异常
     * @param e
     * @return
     */
    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult errorHandle(Exception e){
        log.error("异常信息：{}, {}", e.getMessage(), e);
        return R.fail(CommonStatusCode._1003, e.getMessage());
    }



    /**
     * 解析异常
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult errorHandle(HttpMessageNotReadableException e){
        log.error("异常信息：{}", e.getMessage());
        return R.fail(CommonStatusCode._2005);
    }

    /**
     * 请求类型异常 需要post，但请求是get
     * @param e
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult errorHandle(HttpRequestMethodNotSupportedException e){
        log.error("异常信息：{}", e.getMessage());
        return R.fail(CommonStatusCode._1004);
    }

    /**
     * 请求类型异常 需要json格式，但请求是表单
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult errorHandle(HttpMediaTypeNotSupportedException e){
        log.error("异常信息：{}", e.getMessage());
        return R.fail(CommonStatusCode._1004);
    }


    /**
     * sql异常
     * @param e
     * @return
     */
    @ExceptionHandler(SQLException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult errorHandle(SQLException e){
        log.error("异常信息：{}, {}", e.getMessage(), e);
        return R.fail(CommonStatusCode._1009);
    }

    /**
     * 缺少请求参数。@RequestParam
     * @param e
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult errorHandle(MissingServletRequestParameterException e) {
        log.error("异常信息：{}", e.getMessage());
        return R.fail(CommonStatusCode._2005);
    }


    /**
     * 手动抛出异常
     * @param e
     * @return
     */
    @ExceptionHandler(AppRuntimeException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult errorHandle(AppRuntimeException e){
        log.error("异常信息：{}", e.getMessage());
        return R.fail(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult errorHandle(BindException e){
        List<FieldError> errorList = e.getFieldErrors();
        StringBuilder stringBuilder = getErrorMsg(errorList);
        log.error("异常信息：{}", e.getMessage());
        return R.fail(CommonStatusCode._1003.getCode(), stringBuilder.toString());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult errorHandle(MethodArgumentNotValidException e) {
        List<FieldError> errorList = e.getBindingResult().getFieldErrors();
        StringBuilder stringBuilder = getErrorMsg(errorList);
        log.error("异常信息：{}", e.getMessage());
        return R.fail(CommonStatusCode._1003.getCode(), stringBuilder.toString());
    }

    private StringBuilder getErrorMsg(List<FieldError> errorList) {
        StringBuilder stringBuilder = new StringBuilder();
        for (FieldError error : errorList) {
            stringBuilder.append(error.getField())
                    .append(": ")
                    .append(error.getRejectedValue())
                    .append("【")
                    .append(error.getDefaultMessage())
                    .append("】")
                    .append("; ");
        }
        return stringBuilder;
    }
}
